package com.kla.power.remote;

import com.kla.power.entity.AlarmEntity;
import com.kla.power.entity.InverterAcAmountEntity;
import com.kla.power.entity.InverterDcAmountEntity;
import com.kla.power.entity.InverterElectricEntity;
import com.kla.power.service.IAlarmService;
import com.kla.power.service.IInverterElectricService;
import com.kla.power.util.AlarmUtil;
import com.kla.power.util.CollectorUtil;
import com.kla.power.util.CommonUtil;
import com.kla.power.util.ConstUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.scheduling.annotation.Async;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 监听数采
 */
@Slf4j
public class CollectHandler implements Runnable {

    private Socket socket;
    private IInverterElectricService iInverterElectricService;
    private IAlarmService iAlarmService;

    public CollectHandler ( Socket socket, IInverterElectricService iInverterElectricService, IAlarmService iAlarmService ) {
        this.socket = socket;
        this.iInverterElectricService = iInverterElectricService;
        this.iAlarmService = iAlarmService;
    }


    /**
     * 常规数据：01 62 0D D2 00 00 00 19 00 00 00 28 09 3A 13 88 03 A4 00 05 7E ED 00 00 00 00 00 01 00 00 00 00 02 2C 02 27 00 05 01 2E 0F 2E 13 5D 31 30
     * 身份数据：31 30 30 36 30 30 30 30 30 31 35 33 30 31 33 37 48 4E 53 36 30 30 30 54 4C 00 00 00 41 46 4F 52 45 20 20 20 20 20 20 20 20 20 20 20 53 34 32 36 30 30 30 30 33 31 37 33 30 30 37 38 30 30 30 56 56 31 2D 30 30 30 2D 30 30 30 30 30 31
     */
    @Override
    @Async ( "threadPoolTaskExecutor" )
    public void run () {
        log.info ( "等待逆变器数据..." );
        try {
            BufferedInputStream bis = new BufferedInputStream ( socket.getInputStream () );
            DataInputStream dis = new DataInputStream ( bis );
            byte[] bytes = new byte[1];
            String ret = "";
            while ( dis.read ( bytes ) != - 1 ) {
                // 每次循环表示一组，多组构成同一批数据
                ret += CollectorUtil.bytesToHexString ( bytes ) + " ";
                if ( dis.available () == 0 ) {
                    parseFrame ( ret );
                    ret = "";
                }
            }
        } catch ( Exception e ) {
            e.printStackTrace ();
        } finally {
            log.info ( "客户端断开连接！" );
            if ( socket != null ) {
                try {
                    socket.close ();
                } catch ( IOException e ) {
                    e.printStackTrace ();
                }
            }
        }
    }

    /**
     * 解析十六进制数据，一帧数据总长为135个字节，十六进制规则：
     * 1、前44个字节为逆变器发电常规数据
     * 2、中间77个自己为逆变器身份数据
     * 3、后14个自己为数采SN
     *
     * @param hex
     */
    private void parseFrame ( String hex ) {
        InverterElectricEntity inverterElectricEntity = new InverterElectricEntity ();
        String data = hex.replace ( " ", "" ).toUpperCase ();
        if ( data.length () / 2 == 135 ) {
            log.info ( "报文->[{}]", hex );
            //1.1 解析逆变器数据，前121个数据
            long temp = CollectorUtil.hexToDecimal ( data, 0, 2 );
            inverterElectricEntity.setInverTemp ( CommonUtil.parseDecimalPoint ( 1.0 * temp / 10 ) );

            //解析直流信息
            String dcData = CollectorUtil.parseData ( data, 2, 8 );
            //解析交流信息
            String acData = CollectorUtil.parseData ( data, 10, 6 );
            long gridPower = CollectorUtil.hexToDecimal ( data, 16, 2 );
            inverterElectricEntity.setGridPower ( CommonUtil.parseDecimalPoint ( gridPower ) );
            long totalEnergy = CollectorUtil.hexToDecimal ( data, 18, 4 );
            inverterElectricEntity.setTotaEnergy ( CommonUtil.parseDecimalPoint ( 1.0 * totalEnergy / 10 ) );
            long totalHours = CollectorUtil.hexToDecimal ( data, 22, 4 );
            inverterElectricEntity.setTotalHours ( CommonUtil.parseDecimalPoint ( totalHours ) );
            long model = CollectorUtil.hexToDecimal ( data, 26, 2 );
            inverterElectricEntity.setOperModel ( Integer.parseInt ( String.valueOf ( model ) ) );
            long today = CollectorUtil.hexToDecimal ( data, 32, 2 );
            inverterElectricEntity.setTodayEnergy ( CommonUtil.parseDecimalPoint ( 1.0 * today / 100 ) );
            long a = CollectorUtil.hexToDecimal ( data, 34, 2 );
            inverterElectricEntity.setChannelAEnergy ( CommonUtil.parseDecimalPoint ( 1.0 * a / 100 ) );
            long b = CollectorUtil.hexToDecimal ( data, 36, 2 );
            inverterElectricEntity.setChannelBEnergy ( CommonUtil.parseDecimalPoint ( 1.0 * b / 100 ) );
            long sink = CollectorUtil.hexToDecimal ( data, 38, 2 );
            inverterElectricEntity.setSinkTemp ( CommonUtil.parseDecimalPoint ( 1.0 * sink / 10 ) );
            long bus = CollectorUtil.hexToDecimal ( data, 40, 2 );
            inverterElectricEntity.setBusVoltage ( CommonUtil.parseDecimalPoint ( 1.0 * bus / 10 ) );
            long pwrOnCnt = CollectorUtil.hexToDecimal ( data, 42, 2 );
            inverterElectricEntity.setPwrOnCnt ( Integer.parseInt ( String.valueOf ( pwrOnCnt ) ) );
            //解析逆变器身份数据，全部都是UTF8格式
            String phaseNumber = CollectorUtil.hexToUtf8 ( data, 44, 1 );//相序
            inverterElectricEntity.setPhaseNumber ( phaseNumber );
            String vaRating = CollectorUtil.hexToUtf8 ( data, 45, 6 );
            inverterElectricEntity.setVaRating ( vaRating );
            //固件序列号
            String firmwareVer = CollectorUtil.hexToUtf8 ( data, 51, 9 );
            inverterElectricEntity.setFirmwareVer ( firmwareVer );
            //型号名称
            String madelName = CollectorUtil.hexToUtf8 ( data, 60, 12 );
            inverterElectricEntity.setMadelName ( madelName );
            //制造商
            String manufacturer = CollectorUtil.hexToUtf8 ( data, 72, 16 );
            inverterElectricEntity.setManufacturer ( manufacturer.trim ().replace ( " ", "" ) );
            //SN
            String inverterSn = CollectorUtil.hexToUtf8 ( data, 88, 16 );
            inverterElectricEntity.setSerialNumber ( inverterSn );
            //标称值
            String nomVpv = CollectorUtil.hexToUtf8 ( data, 104, 4 );
            inverterElectricEntity.setNomVpv ( nomVpv );
            String interVersion = CollectorUtil.hexToUtf8 ( data, 108, 13 );
            inverterElectricEntity.setInterVersion ( interVersion );
            //2.1 解析数采SN，后14个字节
            String snData = CollectorUtil.parseData ( data, 121, 135 );
            String sn = CollectorUtil.hexToUtf8 ( snData, 0, snData.length () / 2 );
            inverterElectricEntity.setCollectorSn ( sn );
            // 处理警告
            String alarm = CollectorUtil.parseData ( data, 28, 4 );
            parseAlarm ( alarm, inverterSn );
            //处理直流数据
            parseDc ( dcData, inverterElectricEntity );
            //处理交流数据
            parseAc ( acData, inverterElectricEntity );
            //处理垃圾数据，根据逆变器序列号规则
            if ( checkInverterSn(inverterSn) ) {
                inverterElectricEntity = iInverterElectricService.saveSingle ( inverterElectricEntity );
            }
        } else {
            log.info ( "心跳-> {}", CollectorUtil.hexToUtf8 ( hex, 0, 8 ) );
        }
    }

    /**
     * 解析直流数据入库
     *
     * @param dcData:0D              D2 00 00 00 19 00 00
     * @param inverterElectricEntity
     */
    private void parseDc ( String dcData, InverterElectricEntity inverterElectricEntity ) {
        List<InverterDcAmountEntity> inverterDcAmountEntities = new ArrayList<> ();
        InverterDcAmountEntity pv1 = new InverterDcAmountEntity ();
        long pv1Voltage = CollectorUtil.hexToDecimal ( dcData, 0, 2 );
        pv1.setVoltage ( CommonUtil.parseDecimalPoint ( 1.0 * pv1Voltage / 10 ) );//pv1电压
        long pv1Current = CollectorUtil.hexToDecimal ( dcData, 4, 2 );
        pv1.setCurrent ( CommonUtil.parseDecimalPoint ( 1.0 * pv1Current / 10 ) );//pv1电流
        pv1.setPower ( CommonUtil.ride ( pv1.getVoltage (), pv1.getCurrent () ) );//pv1功率
        pv1.setTitle ( "PV1" );
        inverterDcAmountEntities.add ( pv1 );
        InverterDcAmountEntity pv2 = new InverterDcAmountEntity ();
        long pv2Voltage = CollectorUtil.hexToDecimal ( dcData, 2, 2 );
        pv2.setVoltage ( CommonUtil.parseDecimalPoint ( 1.0 * pv2Voltage / 10 ) );//pv2电压
        long pv2Current = CollectorUtil.hexToDecimal ( dcData, 6, 2 );
        pv2.setCurrent ( CommonUtil.parseDecimalPoint ( 1.0 * pv2Current / 10 ) );//pv2电流
        pv2.setPower ( CommonUtil.ride ( pv2.getVoltage (), pv2.getCurrent () ) );
        pv2.setTitle ( "PV2" );
        inverterDcAmountEntities.add ( pv2 );
        inverterElectricEntity.setInverterDcAmountEntityList ( inverterDcAmountEntities );
    }

    /**
     * 解析交流信息
     *
     * @param acData
     * @param inverterElectricEntity
     */
    private void parseAc ( String acData, InverterElectricEntity inverterElectricEntity ) {
        List<InverterAcAmountEntity> inverterAcAmountEntities = new ArrayList<> ();
        InverterAcAmountEntity r = new InverterAcAmountEntity ();
        long gridCurrent = CollectorUtil.hexToDecimal ( acData, 0, 2 );
        r.setCurrent ( CommonUtil.parseDecimalPoint ( 1.0 * gridCurrent / 10 ) );
        long gridVoltage = CollectorUtil.hexToDecimal ( acData, 2, 2 );
        r.setVoltage ( CommonUtil.parseDecimalPoint ( 1.0 * gridVoltage / 10 ) );
        long gridFrequency = CollectorUtil.hexToDecimal ( acData, 4, 2 );
        r.setRate ( CommonUtil.parseDecimalPoint ( 1.0 * gridFrequency / 100 ) );
        r.setTitle ( "交流1" );
        inverterAcAmountEntities.add ( r );
        inverterElectricEntity.setInverterAcAmountEntityList ( inverterAcAmountEntities );
    }

    /**
     * 调用警告解析，判断发生了哪些异常，入库
     * 警告码为32位二进制码，根据bit位是否为1
     *
     * @param alarm
     * @param inverterSn:逆变器SN
     */
    private void parseAlarm ( String alarm, String inverterSn ) {
        String s = CommonUtil.decimalToBinary ( Integer.parseInt ( String.valueOf ( alarm ) ) );
        s = new StringBuilder ( s ).reverse ().toString ();
        AlarmEntity alarmEntity = new AlarmEntity ();
        for ( int i = 0; i < s.length (); i++ ) {
            if ( s.charAt ( i ) == '1' ) {
                alarmEntity.setType ( ConstUtil.DEVICE_TYPE_INVERTER );
                alarmEntity.setDeviceSn ( inverterSn ); //逆变器SN
                if ( StringUtils.isNotBlank ( AlarmUtil.getAlarm ( i ) ) ) {
                    // 如果今天已发生的警告则不入库
                    alarmEntity.setStatus ( 1 ); //未解决
                    alarmEntity.setAlarmCode ( i + "" );
                    List<AlarmEntity> alarmEntities = iAlarmService.queryTodayList ( alarmEntity );
                    if ( alarmEntities == null || alarmEntities.size () == 0 ) {
                        //表示今天还未发生或者已解决
                        alarmEntity.setAlarmTitle ( AlarmUtil.getAlarm ( i ) );
                        iAlarmService.saveSingle ( alarmEntity );
                    }
                }
            }
        }
    }

    /**
     * 检查逆变器SN是否合理，防止4G发送垃圾数据
     * 根据逆变器序列号基本规则：
     * 1、S开头
     * 2、后面为为15位整数数字
     * @param sn
     * @return
     */
    private boolean checkInverterSn(String sn) {
        if ( StringUtils.isNotBlank ( sn ) ) {
            String regex = "^S[0-9]{15}$";
            Pattern compile = Pattern.compile ( regex );
            Matcher matcher = compile.matcher ( sn );
            return matcher.matches ();
        }
        return false;
    }

}